#ifndef __CORE_COMMON_SYSTEM_H_INCLUDE__
#define __CORE_COMMON_SYSTEM_H_INCLUDE__

#include <core/common/platform.h>
#include <core/common/string.h>

#if defined(OS_PLATFORM_WINDOWS)
	#include <winternl.h>
	#include <winnls.h>
	#include <windows.h> 
#endif

namespace core{ namespace common
{
	class CORE_COMMON_API__ PhysicalMemory
	{
	public:
		uint64 totalBytes_;
		uint64 freeBytes_;
		uint64 buffersBytes_;
		uint64 cachedBytes_;
		uint64 availableBytes_;
		double usagePercent;

		PhysicalMemory()
		{
			totalBytes_   = 0;
			freeBytes_    = 0;
			buffersBytes_ = 0;
			cachedBytes_  = 0;
			availableBytes_ = 0;
			usagePercent   = 0;
		}
	};

	class CORE_COMMON_API__ LogicDisk
	{
	public:
		uint64 totalBytes_;
		uint64 freeBytes_;
		uint64 availableBytes_;
		double usagePercent_;

		LogicDisk()
		{
			totalBytes_ = 0;
			freeBytes_  = 0;
			availableBytes_ = 0;
			usagePercent_   = 0;
		}
	};

	class CORE_COMMON_API__ PhysicalPartition
	{
	public:
		uint64 totalBytes_;
		uint64 freeBytes_;
		uint64 availableBytes_;
		double usagePercent_;
		std::string description;

		PhysicalPartition()
		{
			usagePercent_ = 0;
			totalBytes_ = freeBytes_ = availableBytes_ = 0;
		}

	};
	typedef std::vector<PhysicalPartition> PhysicalPartitionArray;

	class CORE_COMMON_API__ PhysicalDisk
	{
	public:		
		uint64 totalBytes_;				
		std::string description;
	
		PhysicalDisk()
		{			
			totalBytes_ = 0;
		}
	};
	typedef std::vector<PhysicalDisk> PhysicalDiskArray;

	class CORE_COMMON_API__ SystemProcessor
	{
	public:
		size_t coreCount_;
		int64 userTime_;
		int64 niceTime_;
		int64 systemTime_;
		int64 idleTime_;
		int64 ioWaitTime_;
		int64 irqTime_;
		int64 softIrqTime_;
		double usagePercent_;

		SystemProcessor();
		~SystemProcessor();

		int64 getTotalTime();
		int64 getUsageTime();

		static std::string getIdentify();
	};

	typedef std::vector<SystemProcessor> SystemProcessorArray;

	class CORE_COMMON_API__ Process
	{
	public:
		static const uint32 kInvalidId = (uint32)-1;

		uint32 id_;
		uint32 parentId_;
		std::string binaryPath_;
		std::string commandLine_;
		std::string workingPath_;

		bool zombie_;
		uint32 threadCount_;
		uint64 virtualMemorySize_;
		uint64 physicalMemorySize_;
		uint64 userTime_;
		uint64 kernelTime_;
		uint64 creationTime_;

		Process()
		{
			id_       = 0;
			parentId_ = 0;
			zombie_   = false;
			threadCount_ = 0;
			virtualMemorySize_  = 0;
			physicalMemorySize_ = 0;
		}

		//
		// Create process
		// follow parameters is used for windows platform only:
		//     @showWindow, @shellExecute, @plainParameters, @createAsActivatedUser
		//
		static uint32 create( const std::string &file,
			const core::common::StringList &parameters,
			bool  appendStdFile,
			const std::string &stdoutFile,
			const std::string &stderrFile,
			bool showWindow = false,
			bool shellExecute = false,
			int waitMilliSeconds = 0,
			const std::string &workingPath = "",
			bool plainParameters = false,
			bool createAsActivatedUser = false );

		static bool terminate( uint32 processId, bool force = false, uint32 exitCode = 0 );
		static bool terminateAllChilds( uint32 processId, bool force = false, uint32 exitCode = 0 );
		static bool terminateTree( uint32 processId, bool force = false, uint32 exitCode = 0 );
		static bool optimizeAllocateMemory();
		static bool getAllocateMemory( int64 &systemBytes, int64 &inUsedBytes, int64 &inMMapBytes, int64 &inFastBinBytes );
	};

	typedef std::list<Process> ProcessList;

	class CORE_COMMON_API__ System
	{
		DISALLOW_COPY_AND_ASSIGN(System);

	private:
		bool withProcessors_;

#if defined(OS_PLATFORM_WINDOWS)
		typedef NTSTATUS (WINAPI *PROCNTQSI)(UINT,PVOID,ULONG,PULONG);
		HMODULE module_;
		PROCNTQSI pfnNtQuerySystemInformation_;
#endif
	protected:
		SystemProcessor processor_;
		SystemProcessorArray *processorList_;

	public:
		System( bool withProcessors );
		virtual ~System();

		bool updateProcessor();
		inline const SystemProcessor &getProcessor() const{ return processor_; };
		inline SystemProcessorArray *getProcessorList() { return processorList_; };
		static std::string getHostName();
		static std::string getOsVersion();
		static std::string getOsPlatform();
		static bool   getLogicDisk( const std::string &strPath, core::common::LogicDisk &disk );
		static bool   getPhysicalMemory( core::common::PhysicalMemory &memory );
		static time_t getStartupTime( time_t timeNow = 0 );
		static bool   getProcessList( core::common::ProcessList &list );
		static bool   getCurrentProcess( core::common::Process &process );
		static bool   getPhysicalDiskList( core::common::PhysicalDiskArray &diskes, core::common::PhysicalPartitionArray &partitions );

		static bool checkSystemUser( const std::string &user, const std::string &password );
		static bool changeSystemPassword(const std::string &username, const std::string &odPassword, const std::string &newPassword);
		static bool rebootSystem();
	};
}}

#endif //__CORE_COMMON_SYSTEM_H_INCLUDE__
